import numpy as np

##原始版本(使用此原始方式，其运算是针对指数的运算，十分容易出现计算溢出，为此，对原公式进行等价替换，故有版本2.0出现，见下)
def softmax(x):
    exp_x = np.exp(x)
    sum_exp_x = np.sum(exp_x)
    y = exp_x/sum_exp_x
    return y

##优化版本
def softmax_2(x):
    c = np.max(x)  #取出输入信号中的最大值
    exp_x = np.exp(x - c)  #将原输入信号数组进行放小处理，注意，这种处理并不会影响最后的输出结果（你可以尝试数学公式证明一下，我暂时证明不出来）
    y = exp_x/np.sum(exp_x)
    return y




if __name__ == '__main__':
    print("------试试看书中的公式等价代换是否真实可行------")
    x = np.array([10.0,11.0])
    print(x)
    print(softmax(x))
    max = np.max(x)
    print(x - max)
    print(softmax(x - max))
    print("---------大数值指数运算尝试-----------")
    x_big = np.array([1010,1000,990])
    print("--原始公式处理--")
    print(softmax(x_big))  #计算将会失败，指数值过大，计算结果数值无法被有效表示出来
    print("--优化版本公式处理--")
    print(softmax_2(x_big))  #[9.99954600e-01 4.53978686e-05 2.06106005e-09]
    print("------尝试放入一些输入，验证公式的正确性（我已经提前知道这些输入的输出）------")
    x_1 = np.array([0.3,2.9,4.0])
    y_1 = softmax_2(x_1)
    print(y_1)  #[0.01821127 0.24519181 0.73659691] 等同 y_1[0]出现概率1.8%；y_1[1]出现概率24%；y_1[2]出现概率73%；
    y_1_sum = np.sum(y_1)  #求和为1，而且总是如此，也该如此，不是吗？
    print(y_1_sum)



